package yto.freemarker.springbootstudy.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

/**
 * 银行交易系统
 * <p>
 * 网址：https://open.toutiao.com/a6541718568008942093/?utm_campaign=open&utm_medium=webview&utm_source=vivoliulanqi&item_id=6541718568008942093&os=Android&gy=d37dd9247599f47bbf3147c15bf63d93271d70bca4a35e82a655acd94b99b3e04ccc2e975c870e572632a8d487416e7092da0716b8ddd1c25b2b333adeb2135d&uuid=862681036704785&openudid=61a145043f6fe90f&label=headline&crypt=2726&isNews=1&showComments=0&vivo_news_comment_data=%7B%7D&vivo_news_comment_data_checksum=99914b932bd37a50b983c5e7c90ae93b
 * <p>
 * <p>
 * 场景：远程调用银行的扣款服务，扣款成功/失败，更新本地数据库订单状态
 * <p>
 * 解决方法：
 * 1：缩小事务范围，引入编程式事务（TransactionTemplate）。
 * 2：增加订单业务状态（处理中）。后续针对处理中的订单进行对账。
 * <p>
 * <p>
 * 解决扣款请求重复时候的，重复扣款的问题
 * 请求的幂等性处理，考虑到高并发的情况，需要进行加锁操作，例如redis锁，数据库锁。
 *
 * @author dongxing
 * @create 2018-05-30 10:40
 **/
@Slf4j
public class YinHangPay {

    @Autowired
    private TransactionTemplate transactionTemplate;

//    @Transactional(propagation = Propagation.NEVER)
//    public void pay(Order order) {
//        try {
//            //首先要获取锁，才能继续处理
//            Boolean lockStatus = transactionTemplate.execute(new TransactionCallback<Integer>() {
//                @Override
//                public Integer doInTransaction(TransactionStatus status) {
//                    //构造update语句
//                    //update order set status = on（处理中） where id= ? and status = 0(初始值)
//                    int result = orderMapper.update(order);
//                    return result;
//                }
//            });
//            if (lockStatus) {
//                //远程回调的信息
//                RespEntity<Object> respEntity = bankService.outMoney(order);
//                if (respEntity != null) {
//                    if (respEntity.getKey().equals("0000")) {
//                        //下单成功
//                        order.setStatus("OK");
//                    } else {
//                        //处理失败
//                        order.setStatus("NG");
//                    }
//                    //编程式事务
//                    transactionTemplate.execute(new TransactionCallback<String>() {
//                        @Override
//                        public String doInTransaction(TransactionStatus status) {
//                            orderMapper.update(order);
//                            return null;
//                        }
//                    });
//                }
//            } else {
//                log.error("获取锁失败");
//            }
//        } catch (Exception e) {
//            log.error("下单失败", e);
//            throw e;
//        }
//    }
}
